package com.crazymaker.l2cache.monitor;


import com.crazymaker.l2cache.manager.CacheChannel;
import com.crazymaker.springcloud.common.util.RandomUtil;
import com.crazymaker.springcloud.common.util.ThreadUtil;
import io.micrometer.core.instrument.MeterRegistry;
import lombok.Data;

import java.util.concurrent.atomic.AtomicLong;

@Data
public class PrometheusCustomMonitor {

    private final CacheChannel cacheChannel;
    private final HitRecordService hitRecordService;
    private final MisRecordService misRecordService;
    private long rawHitAmount;
    private long rawMisAmount;
    private long totalAmount;

    public void addHit() {
        hitRecordService.incrementHit();
    }

    public void addMis() {
        misRecordService.incrementMis();
    }

    public void recordHit(long rawHitAmount) {
        this.rawHitAmount = rawHitAmount;
        compute();
    }

    public void recordMis(long rawMisAmount) {
        this.rawMisAmount = rawMisAmount;
        compute();
    }

    private void compute() {
        totalAmount = this.rawHitAmount + rawMisAmount;

        //使用次数
        useCountGauge.set(totalAmount);
        // 命中率
        hitRateGauge.set((long) (((double)rawHitAmount / (double)totalAmount) * 100));
    }

    /**
     * 使用次数
     */
    private AtomicLong useCountGauge;

    /**
     * 命中率
     */
    private AtomicLong hitRateGauge;


    private final MeterRegistry registry;

    public PrometheusCustomMonitor(MeterRegistry meterRegistry, CacheChannel cacheChannel) {
        this.registry = meterRegistry;
        this.cacheChannel = cacheChannel;

        hitRecordService = new HitRecordService(cacheChannel, this);
        misRecordService = new MisRecordService(cacheChannel, this);
    }

    public void init() {
        useCountGauge = registry.gauge("cache_use_count",new AtomicLong(0));
        hitRateGauge = registry.gauge("cache_hit_rate",new AtomicLong(0));
        hitRecordService.start();
        misRecordService.start();
        mock();

    }

    private void mock() {
        new Thread(() -> {
            while (true) {
                ThreadUtil.sleepMilliSeconds(1000);
                int mis = RandomUtil.randInMod(100);
                PrometheusCustomMonitor.this.recordMis(mis);
                int hit = RandomUtil.randInMod(100);
                PrometheusCustomMonitor.this.recordHit(hit);
             }
        }).start();
    }

}